class EventEmitter {
  constructor() {
    this.events = {}
  }
  on(eventName, fn) {
    let fnList = this.events[eventName] || (this.events[eventName] = [])
    fnList.push(fn)
    this.events[eventName] = fnList
  }
  emit(eventName) {
    const keys = Object.keys(this.events)
    keys.forEach(key => {
      if (key === eventName) {
        this.events[key].forEach(fn => {
          fn()
        })
      }
    })
  }
  off(eventName, cb) {
    if (!eventName) {
      this.events = {}
    } else if (!cb) {
      this.events[eventName] = []
    } else {
      let fnList = this.events[eventName]
      fnList && fnList.forEach((fn, index) => {
        if (fn === cb) {
          fnList = fnList.splice(index, 1)
        }
      })
    }
  }
  once(eventName, fn) {
    let cb = () => {
      fn()
      this.off(eventName, cb)
    }
    this.on(eventName, cb)
  }
}

let test = new EventEmitter()
test.on('hello', () => {
  console.log('hello')
})
test.on('hello', () => {
  console.log('world')
})
test.emit('hello')
test.off('hello', () => {
  console.log('hello')
})
test.emit('hello')
test.once('nihao', () => {
  console.log('nihao')
})
test.emit('nihao')
test.emit('nihao')